/*
 * @Author: 0x9DEFA478
 * @Date: 2025-06-17 21:07:52
 * @LastEditTime: 2025-08-11 22:44:18
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * 
 */
#include "./C_Printf.h"
#include "../Utility/H_StringFormat.h"
#include <stdio.h>
#if defined(_WIN32)&&(vC_Printf_BypassEncode==0)
#include "../Utility/H_Unicode.h"
#include <windows.h>
#endif




#if defined(_WIN32)||defined(__linux__)

static inline int std_output(const char* Buffer,int Length){
  int res;

  res=fwrite(Buffer,1,Length,stdout);
  if(res!=Length){
    return -1;
  }
  return 0;
}
static inline void std_output_flush(){
  fflush(stdout);
}

typedef struct{
  H_StringFormat_CharOutput CharOutput;
#if defined(_WIN32)&&(vC_Printf_BypassEncode==0)
  int InBufferIndex;
  char InBuffer[16];
  WCHAR WCharBuffer[16];
  char OutBuffer[16];
#endif
}std_C_CharOutput_t;

#if defined(_WIN32)&&(vC_Printf_BypassEncode==0)

static int ConvertOutput(std_C_CharOutput_t* std_C_CharOutput,int IsFlush){
  int res;
  int ValidLength;
  int IsError;
  int InBufferIndex;
  char* InBuffer;

  InBuffer=std_C_CharOutput->InBuffer;
  InBufferIndex=std_C_CharOutput->InBufferIndex;

  if((IsFlush==0)&&(InBufferIndex<(sizeof(std_C_CharOutput->InBuffer)/sizeof(std_C_CharOutput->InBuffer[0])/2))){
    return 0;
  }

  ValidLength=(int)H_UTF8_ValidLength(InBuffer,InBufferIndex,&IsError);

  if(ValidLength>0){
    char* OutBuffer;
    
    OutBuffer=std_C_CharOutput->OutBuffer;
    
    res=MultiByteToWideChar(CP_UTF8,0,InBuffer,ValidLength,std_C_CharOutput->WCharBuffer,sizeof(std_C_CharOutput->WCharBuffer)/sizeof(std_C_CharOutput->WCharBuffer[0]));
    res=WideCharToMultiByte(GetConsoleOutputCP(),0,std_C_CharOutput->WCharBuffer,res,OutBuffer,sizeof(std_C_CharOutput->OutBuffer)/sizeof(std_C_CharOutput->OutBuffer[0]),NULL,NULL);
  
    std_output(OutBuffer,res);

  }

  {
    int length;
    int shiftCount;

    shiftCount=ValidLength+IsError;
    length=InBufferIndex-shiftCount;

    for(int i=0;i<length;i++){
      InBuffer[i]=InBuffer[shiftCount+i];
    }

    std_C_CharOutput->InBufferIndex=length;
  }

  if(InBufferIndex>=(sizeof(std_C_CharOutput->InBuffer)/sizeof(std_C_CharOutput->InBuffer[0])-1)){
    std_C_CharOutput->InBufferIndex=0;
  }

  return 0;
}

#endif

static int std_CharOutput(H_StringFormat_CharOutput* CharOutput,char c){

#if defined(_WIN32)&&(vC_Printf_BypassEncode==0)
  std_C_CharOutput_t* std_C_CharOutput;
  int InBufferIndex;

  std_C_CharOutput=cH_GetParentPointer(CharOutput,std_C_CharOutput_t,CharOutput);

  InBufferIndex=std_C_CharOutput->InBufferIndex;
  std_C_CharOutput->InBuffer[InBufferIndex]=c;
  InBufferIndex++;
  std_C_CharOutput->InBufferIndex=InBufferIndex;

  return ConvertOutput(std_C_CharOutput,0);

#else
  return std_output(&c,1);
#endif

}

static void std_CharOutput_flush(H_StringFormat_CharOutput* CharOutput){

#if defined(_WIN32)&&(vC_Printf_BypassEncode==0)
  std_C_CharOutput_t* std_C_CharOutput;

  std_C_CharOutput=cH_GetParentPointer(CharOutput,std_C_CharOutput_t,CharOutput);

  ConvertOutput(std_C_CharOutput,1);

#endif

  std_output_flush();
}


int C_Printf(const char* Format,...){
  va_list Params;
  std_C_CharOutput_t I_std_C_CharOutput={0};
  int r;
  
  va_start(Params,Format);

  I_std_C_CharOutput.CharOutput.Output=std_CharOutput;
  r=H_StringFormat(&I_std_C_CharOutput.CharOutput,Format,&Params);

  va_end(Params);

  std_CharOutput_flush(&I_std_C_CharOutput.CharOutput);


  return r;
}

#endif



